package com.management.department.teacherinfosystem.Controller;

import com.fasterxml.jackson.databind.ObjectMapper;

import java.io.File;
import java.util.*;
import java.util.stream.Collectors;
import java.text.SimpleDateFormat;

import com.management.department.teacherinfosystem.DTO.FinishDTO;
import com.management.department.teacherinfosystem.DTO.ReviewDTO;
import com.management.department.teacherinfosystem.Entity.Attachment;
import com.management.department.teacherinfosystem.Entity.TeachingProject;
import com.management.department.teacherinfosystem.Entity.TeachingProjectMember;
import com.management.department.teacherinfosystem.Entity.User;
import com.management.department.teacherinfosystem.Entity.ProjectFunding;
import com.management.department.teacherinfosystem.Repository.AttachmentRepository;
import com.management.department.teacherinfosystem.Repository.TeachingProjectRepository;
import com.management.department.teacherinfosystem.Repository.TeachingProjectMemberRepository;
import com.management.department.teacherinfosystem.Repository.UserRepository;
import com.management.department.teacherinfosystem.Repository.ProjectFundingRepository;

import com.management.department.teacherinfosystem.DTO.ProjectSubmitDTO;
import com.management.department.teacherinfosystem.Service.ProjectService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.transaction.annotation.Transactional;

@RestController
@RequestMapping("/api/projects")
public class ProjectController {

    @Autowired
    private ProjectService projectService;

    @Autowired
    private UserRepository userRepository;

    @Autowired
    private TeachingProjectRepository projectRepository;

    @Autowired
    private TeachingProjectMemberRepository memberRepository;

    @Autowired
    private AttachmentRepository attachmentRepository;

    @Autowired
    private ProjectFundingRepository fundingRepository;

    @Value("${file.upload.finish-dir}")
    private String finishUploadDir;

    // 查询所有项目（带经费总额）- 放在最前面确保优先级
    @GetMapping(value = "/list", produces = "application/json")
    @Transactional(readOnly = true)
    public List<Map<String, Object>> getAllProjects() {
        try {
            // 获取当前登录用户
            org.springframework.security.core.Authentication auth = 
                org.springframework.security.core.context.SecurityContextHolder.getContext().getAuthentication();
            String currentUsername = auth.getName();
            User currentUser = userRepository.findByUsernameWithRoles(currentUsername).orElse(null);
            
            if (currentUser == null) {
                return new ArrayList<>();
            }
            
            List<TeachingProject> projects;
            
            // 检查用户是否为管理员
            boolean isAdmin = currentUser.getUserRoles().stream()
                .anyMatch(userRole -> "admin".equals(userRole.getRole().getName()));
            
            if (isAdmin) {
                // 管理员可以查看所有项目
                projects = projectRepository.findAll();
            } else {
                // 普通用户只能查看自己相关的项目（负责人为自己，或者是项目成员）
                List<TeachingProject> myLeaderProjects = projectRepository.findByLeaderId(currentUser.getId());
                List<Long> memberProjectIds = memberRepository.findByUserId(currentUser.getId())
                    .stream()
                    .map(TeachingProjectMember::getProjectId)
                    .collect(Collectors.toList());
                
                projects = new ArrayList<>(myLeaderProjects);
                if (!memberProjectIds.isEmpty()) {
                    List<TeachingProject> memberProjects = projectRepository.findAllById(memberProjectIds);
                    // 避免重复添加
                    for (TeachingProject memberProject : memberProjects) {
                        if (projects.stream().noneMatch(p -> p.getId().equals(memberProject.getId()))) {
                            projects.add(memberProject);
                        }
                    }
                }
            }
            
            List<Map<String, Object>> result = new ArrayList<>();
            
            for (TeachingProject project : projects) {
                Map<String, Object> projectWithFunding = new HashMap<>();
                projectWithFunding.put("id", project.getId());
                projectWithFunding.put("name", project.getName());
                projectWithFunding.put("projectType", project.getProjectType());
                projectWithFunding.put("level", project.getLevel());
                projectWithFunding.put("status", project.getStatus());
                projectWithFunding.put("startDate", project.getStartDate());
                projectWithFunding.put("endDate", project.getEndDate());
                projectWithFunding.put("createdAt", project.getCreatedAt());
                projectWithFunding.put("updatedAt", project.getUpdatedAt());
                projectWithFunding.put("leaderId", project.getLeaderId());
                
                // 安全地获取经费总额
                try {
                    List<ProjectFunding> fundings = fundingRepository.findByProjectId(project.getId());
                    double totalFunding = fundings.stream()
                            .mapToDouble(f -> f.getAmount().doubleValue())
                            .sum();
                    projectWithFunding.put("totalFunding", totalFunding);
                } catch (Exception e) {
                    // 如果经费查询失败，设为0
                    projectWithFunding.put("totalFunding", 0.0);
                }
                
                // 获取负责人姓名
                String leaderName = "";
                if (project.getLeaderId() != null) {
                    var leader = userRepository.findById(project.getLeaderId());
                    if (leader.isPresent()) {
                        leaderName = leader.get().getName();
                    }
                }
                projectWithFunding.put("leaderName", leaderName);
                
                result.add(projectWithFunding);
            }
            
            return result;
        } catch (Exception e) {
            e.printStackTrace();
            return new ArrayList<>();
        }
    }

    // 接收申报（项目+成员+附件）
    @PostMapping
    public ResponseEntity<?> submitProject(
            @RequestPart("data") String data,
            @RequestPart(value = "files", required = false) MultipartFile[] files
    ) {
        try {
            // 参数验证
            if (data == null || data.trim().isEmpty()) {
                return ResponseEntity.badRequest().body("项目数据不能为空");
            }

            // 反序列化JSON为DTO
            ObjectMapper mapper = new ObjectMapper();
            ProjectSubmitDTO dto;
            try {
                dto = mapper.readValue(data, ProjectSubmitDTO.class);
            } catch (Exception e) {
                return ResponseEntity.badRequest().body("项目数据格式错误：" + e.getMessage());
            }

            // 基本字段验证
            if (dto.getName() == null || dto.getName().trim().isEmpty()) {
                return ResponseEntity.badRequest().body("项目名称不能为空");
            }
            if (dto.getName().length() > 128) {
                return ResponseEntity.badRequest().body("项目名称长度不能超过128个字符");
            }
            if (dto.getProjectType() == null || dto.getProjectType().trim().isEmpty()) {
                return ResponseEntity.badRequest().body("项目类型不能为空");
            }
            if (dto.getLevel() == null || dto.getLevel().trim().isEmpty()) {
                return ResponseEntity.badRequest().body("项目级别不能为空");
            }

            // 文件验证
            if (files != null) {
                long totalSize = 0;
                for (MultipartFile file : files) {
                    if (file.getSize() > 50 * 1024 * 1024) { // 50MB单文件限制
                        return ResponseEntity.badRequest().body("文件 " + file.getOriginalFilename() + " 大小超过50MB限制");
                    }
                    totalSize += file.getSize();
                }
                if (totalSize > 100 * 1024 * 1024) { // 100MB总限制
                    return ResponseEntity.badRequest().body("上传文件总大小超过100MB限制");
                }
                if (files.length > 10) {
                    return ResponseEntity.badRequest().body("最多只能上传10个文件");
                }
            }

            // 交给Service处理
            Long projectId = projectService.saveProjectWithMembersAndFile(dto, files);

            return ResponseEntity.ok("申报成功，项目ID: " + projectId);

        } catch (RuntimeException e) {
            // 处理业务逻辑异常
            String errorMsg = e.getMessage();
            if (errorMsg.contains("负责人不存在") || errorMsg.contains("当前用户不存在")) {
                return ResponseEntity.badRequest().body("用户信息错误：" + errorMsg);
            } else if (errorMsg.contains("未登录或认证信息丢失")) {
                return ResponseEntity.status(401).body("认证失败：" + errorMsg);
            } else if (errorMsg.contains("日期")) {
                return ResponseEntity.badRequest().body("日期格式错误：" + errorMsg);
            } else {
                return ResponseEntity.status(500).body("系统错误：" + errorMsg);
            }
        } catch (Exception e) {
            // 处理其他异常
            return ResponseEntity.status(500).body("系统异常：" + e.getMessage());
        }
    }



    // 查询所有"申报中"项目
    @GetMapping("/pending")
    public List<TeachingProject> getPendingProjects() {
        return projectRepository.findByStatus("申报中");
    }

    // 查询需要审核的项目（管理员使用）
    @GetMapping("/for-review")
    public List<TeachingProject> getProjectsForReview() {
        return projectRepository.findByStatusIn(List.of("申报中", "结题审核中"));
    }

    // 查询各状态的项目
    @GetMapping("/by-status/{status}")
    public List<TeachingProject> getProjectsByStatus(@PathVariable("status") String status) {
        return projectRepository.findByStatus(status);
    }

    // 查询项目详情（含成员、附件、经费）
    // ProjectController.java
    @GetMapping("/{id:[0-9]+}")
    public Map<String, Object> getProjectDetail(@PathVariable("id") Long id) {
        TeachingProject project = projectRepository.findById(id).orElse(null);
        List<TeachingProjectMember> members = memberRepository.findByProjectId(id);
        // 组装每个成员的姓名/工号/部门
        for (TeachingProjectMember m : members) {
            User u = userRepository.findById(m.getUserId()).orElse(null);
            if (u != null) {
                m.setName(u.getName());
                m.setStaffNo(u.getStaffNo());
                m.setDepartment(u.getDepartment());
            }
        }

        // 负责人姓名补全（不会影响成员逻辑，只是多加一个返回字段）
        String leaderName = null;
        if (project != null && project.getLeaderId() != null) {
            User leader = userRepository.findById(project.getLeaderId()).orElse(null);
            if (leader != null) {
                leaderName = leader.getName();
            }
        }

        // 获取经费信息
        List<ProjectFunding> fundings = fundingRepository.findByProjectId(id);
        double totalFunding = fundings.stream()
                .mapToDouble(f -> f.getAmount().doubleValue())
                .sum();

        List<Attachment> attachments = attachmentRepository.findByRelatedTypeAndRelatedId("teaching_project", id);
        return Map.of(
                "project", project,
                "leaderName", leaderName,   // 负责人
                "members", members,
                "fundings", fundings,       // 经费列表
                "totalFunding", totalFunding, // 经费总计
                "attachments", attachments
        );
    }


    @PostMapping("/{id:[0-9]+}/review")
    @PreAuthorize("hasRole('ADMIN')")
    public ResponseEntity<?> reviewProject(
            @PathVariable("id") Long id,
            @RequestBody ReviewDTO reviewDTO
    ) {
        System.out.println("=== 审核开始 ===");
        System.out.println("DEBUG: 审核项目ID=" + id);
        System.out.println("DEBUG: 审核结果=" + reviewDTO.getStatus());
        System.out.println("DEBUG: 审核意见=" + reviewDTO.getOpinion());
        
        TeachingProject project = projectRepository.findById(id).orElse(null);
        if (project == null) {
            return ResponseEntity.notFound().build();
        }
        
        System.out.println("DEBUG: 项目当前状态=" + project.getStatus());

        // 获取当前用户
        org.springframework.security.core.Authentication auth = 
            org.springframework.security.core.context.SecurityContextHolder.getContext().getAuthentication();
        String currentUsername = auth.getName();
        User reviewer = userRepository.findByUsername(currentUsername).orElse(null);
        if (reviewer == null) {
            return ResponseEntity.badRequest().body("审核人信息不存在");
        }

        // 记录审核信息到对应字段
        System.out.println("DEBUG: 项目ID=" + id + ", 当前状态=" + project.getStatus() + ", 审核意见=" + reviewDTO.getOpinion());
        
        // 判断是否为结题审核：检查项目是否有结题信息
        boolean isFinishReview = "结题审核中".equals(project.getStatus()) 
                                || (project.getFinishDate() != null)
                                || (project.getFinishType() != null && !project.getFinishType().trim().isEmpty());
        
        System.out.println("DEBUG: 是否为结题审核=" + isFinishReview);
        
        if (isFinishReview) {
            // 结题审核，记录到结题审核意见字段
            System.out.println("DEBUG: 保存到结题审核意见字段");
            project.setFinishReviewOpinion(reviewDTO.getOpinion());
            project.setFinishReviewerId(reviewer.getId());
            project.setFinishReviewTime(new Date());
        } else {
            // 申报审核，记录到申报审核意见字段
            System.out.println("DEBUG: 保存到申报审核意见字段");
            project.setReviewOpinion(reviewDTO.getOpinion());
            project.setReviewerId(reviewer.getId());
            project.setReviewTime(new Date());
        }

        // 根据流程图和当前状态进行状态流转
        if ("已通过".equals(reviewDTO.getStatus())) {
            if ("申报中".equals(project.getStatus())) {
                project.setStatus("已立项");
                project.setApprovalDate(new Date()); // 设置立项日期
            } else if ("结题审核中".equals(project.getStatus())) {
                project.setStatus("已结题");
            }
        } else if ("已驳回".equals(reviewDTO.getStatus())) {
            project.setStatus("已驳回");
        }
        
        project.setUpdatedAt(new Date());
        
        System.out.println("DEBUG: 保存后项目状态=" + project.getStatus());
        System.out.println("DEBUG: 申报审核意见=" + project.getReviewOpinion());
        System.out.println("DEBUG: 结题审核意见=" + project.getFinishReviewOpinion());
        System.out.println("=== 审核结束 ===");
        
        projectRepository.save(project);
        
        return ResponseEntity.ok("审核完成");
    }

    @GetMapping("/my")
    public List<TeachingProject> getMyProjects(@RequestParam("userId") Long userId) {
        // 假设TeachingProject表有leaderId字段（即申报人/负责人ID）
        return projectRepository.findByLeaderId(userId);
    }

    @PostMapping("/{id:[0-9]+}/resubmit")
    public ResponseEntity<?> resubmitProject(
            @PathVariable("id") Long id,
            @RequestPart("data") String data,
            @RequestPart(value = "files", required = false) MultipartFile[] files
    ) throws Exception {
        // 手动反序列化
        ObjectMapper mapper = new ObjectMapper();
        ProjectSubmitDTO dto = mapper.readValue(data, ProjectSubmitDTO.class);

        projectService.resubmitProject(id, dto, files);
        return ResponseEntity.ok("重新提交成功！");
    }

    // 开始执行项目（立项后转为执行中）
    @PostMapping("/{id:[0-9]+}/start-execution")
    public ResponseEntity<?> startProjectExecution(@PathVariable("id") Long id) {
        TeachingProject project = projectRepository.findById(id).orElse(null);
        if (project == null) {
            return ResponseEntity.notFound().build();
        }
        
        if (!"已立项".equals(project.getStatus())) {
            return ResponseEntity.badRequest().body("只有已立项的项目才能开始执行");
        }
        
        project.setStatus("执行中");
        project.setUpdatedAt(new Date());
        projectRepository.save(project);
        
        return ResponseEntity.ok("项目已开始执行");
    }

    // 删除项目
    @DeleteMapping("/{id:[0-9]+}")
    @Transactional
    public ResponseEntity<?> deleteProject(@PathVariable("id") Long id) {
        try {
            TeachingProject project = projectRepository.findById(id).orElse(null);
            if (project == null) {
                return ResponseEntity.notFound().build();
            }

            // 获取当前登录用户
            org.springframework.security.core.Authentication auth = 
                org.springframework.security.core.context.SecurityContextHolder.getContext().getAuthentication();
            String currentUsername = auth.getName();
            User currentUser = userRepository.findByUsernameWithRoles(currentUsername).orElse(null);
            
            if (currentUser == null) {
                return ResponseEntity.status(401).body("用户未登录");
            }

            // 检查权限：只有项目负责人或管理员可以删除
            boolean isAdmin = currentUser.getUserRoles().stream()
                .anyMatch(userRole -> "admin".equals(userRole.getRole().getName()));
            boolean isProjectLeader = project.getLeaderId().equals(currentUser.getId());

            if (!isAdmin && !isProjectLeader) {
                return ResponseEntity.status(403).body("权限不足，只有项目负责人或管理员可以删除项目");
            }

            // 检查项目状态：只能删除申报中或已驳回的项目
            if (!"申报中".equals(project.getStatus()) && !"已驳回".equals(project.getStatus())) {
                return ResponseEntity.badRequest().body("只能删除申报中或已驳回的项目");
            }

            // 调用Service层删除方法（有事务支持）
            projectService.deleteProject(id);
            
            return ResponseEntity.ok("项目删除成功");
            
        } catch (Exception e) {
            e.printStackTrace();
            return ResponseEntity.status(500).body("删除失败：" + e.getMessage());
        }
    }

    @PostMapping("/{id:[0-9]+}/finish")
    public ResponseEntity<?> finishProject(
            @PathVariable("id") Long id,
            @RequestPart("data") String data, // JSON字符串
            @RequestPart(value = "files", required = false) MultipartFile[] files // 附件
    ) throws Exception {
        TeachingProject project = projectRepository.findById(id).orElse(null);
        if (project == null) return ResponseEntity.notFound().build();

        ObjectMapper mapper = new ObjectMapper();
        FinishDTO dto = mapper.readValue(data, FinishDTO.class);

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        if (!"执行中".equals(project.getStatus())) {
            return ResponseEntity.badRequest().body("只有执行中的项目才能提交结题");
        }

        project.setFinishDate(dto.getFinishDate() != null ? sdf.parse(dto.getFinishDate()) : null);
        project.setFinishType(dto.getFinishType());
        project.setFinishLevel(dto.getFinishLevel());
        project.setFinishResults(dto.getFinishResults());
        project.setStatus("结题审核中");  // 根据流程图，提交结题后进入结题审核中状态
        project.setUpdatedAt(new Date());
        projectRepository.save(project);

        // 只要有结题材料（file），就存到附件表
        if (files != null && files.length > 0) {
            for (MultipartFile file : files) {
                if (file.isEmpty()) continue;
                File dir = new File(finishUploadDir);
                if (!dir.exists()) dir.mkdirs();
                String saveName = System.currentTimeMillis() + "_" + file.getOriginalFilename();
                File dest = new File(finishUploadDir + saveName);
                file.transferTo(dest);

                Attachment attachment = new Attachment();
                attachment.setFileName(file.getOriginalFilename());
                attachment.setFileUrl(finishUploadDir + saveName);
                attachment.setRelatedType("project_finish");
                attachment.setRelatedId(id); // 关联到项目ID
                attachment.setUploadedAt(new Date());
                attachmentRepository.save(attachment);
            }
        }

        return ResponseEntity.ok("结题材料提交成功");
    }


    @GetMapping("/check")
    public Map<String, Object> checkUserByStaffNo(@RequestParam("staffNo") String staffNo) {
        var opt = userRepository.findByStaffNo(staffNo.trim());
        boolean exist = opt.isPresent();
        if (exist) {
            User u = opt.get();
            return Map.of(
                    "exist", true,
                    "name", u.getName(),
                    "department", u.getDepartment(),
                    "userId", u.getId()
            );
        }
        return Map.of("exist", false);
    }
}
